package com.xbongbong.paas.model.impl;

import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.domain.dao.PaasProcessTemplateDao;
import com.xbongbong.paas.domain.entity.PaasProcessTemplateEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.saas.constant.ParameterConstant;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author: wufeng
 * @date: 2018/8/13 15:22
 * @desrcption: PaaS流程设计实现类
 */
@Service("paasProcessTemplateModel")
public class PaasProcessTemplateModelImpl implements PaasProcessTemplateModel {

    private static final String COLUMNS = " id, corpid, app_id, menu_id, form_id, saas_mark, business_type, name,allow_edit_after_finished, roles_without_approve, need_approve_fields, allow_withdraw, allow_view_log, enable, empty_approver_type, creator_id, add_time, update_time, del, type, version_id, version_name, use_permission , approver_dedup , auto_approved_pass ";


    @Resource
    private PaasProcessTemplateDao processTemplateDao;

    @Override
    public Integer insert(PaasProcessTemplateEntity entity) {
        long now = DateUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        return processTemplateDao.insert(entity);
    }

    @Override
    public List<PaasProcessTemplateEntityExt> list(Map<String, Object> map) {
        if (!map.containsKey(ParameterConstant.COLUMNS)) {
            map.put(ParameterConstant.COLUMNS, new StringBuffer(COLUMNS).append(", roles_without_approve as roles_without_approve_list, need_approve_fields as need_approve_field_list , is_archive "));
        }
        return processTemplateDao.findEntitys(map);
    }

    @Override
    public PaasProcessTemplateEntityExt getByKey(Long key, String corpid) {

        return processTemplateDao.getByKey(key, corpid);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> map) {
        return processTemplateDao.getEntitysCount(map);
    }

    @Override
    public Integer delete(PaasProcessTemplateEntity entity) {
        return  processTemplateDao.deleteByKey(entity.getId().intValue(), entity.getCorpid());
    }

    @Override
    public Integer update(PaasProcessTemplateEntity entity) {
        long now = DateUtil.getInt();
        entity.setUpdateTime(now);
        return processTemplateDao.update(entity);
    }

    @Override
    public boolean getEditAfterFinished(Long appId, Long menuId, Long formId, UserVO loginUser) {
        // 主动抛出无corpid的运行时异常
        if (StringUtil.isEmpty(loginUser.getCorpid())) {
            throw new IllegalArgumentException("loginUser 中的corpid参数为空");
        }
        // 获取流程设置审批后是否可编辑
        boolean isAdminOrBoss = loginUser.isAdminOrBoss();
        if (isAdminOrBoss) {
            // 老板和管理员审批通过以后总是允许编辑
            return true;
        }
        Map<String, Object> params = new HashMap<>();
        // 先从loginUser中获取corpid
        params.put("corpid", loginUser.getCorpid());
        params.put("appId",appId);
        params.put("menuId",menuId);
        params.put("formId",formId);
        params.put("del",0);
        params.put("enable",1);
        List<PaasProcessTemplateEntityExt> templateList = list(params);
        if (CollectionUtils.isEmpty(templateList)) {
            // 无流程设置可以编辑
            return true;
        }
        PaasProcessTemplateEntityExt paasProcessTemplateEntityExt = templateList.get(0);
        Integer editAfterFinished = paasProcessTemplateEntityExt.getAllowEditAfterFinished();
        return 1 == editAfterFinished;
    }


    @Override
    public Map<Long, Boolean> getEditAfterFinishedMap(String corpid, Long appId, Long menuId, UserVO loginUser) {
        Map<Long, Boolean> formIdAndEditEnale = new HashMap<>();
        // 获取流程设置审批后是否可编辑
        boolean isAdminOrBoss = loginUser.isAdminOrBoss();
        if (isAdminOrBoss) {
            // 老板和管理员审批通过以后总是允许编辑
            return formIdAndEditEnale;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("corpid", corpid);
        params.put("appId", appId);
        params.put("menuId", menuId);
        params.put("del", 0);
        params.put("enable", 1);
        List<PaasProcessTemplateEntityExt> templateList = list(params);
        if (CollectionUtils.isEmpty(templateList)) {
            // 无流程设置可以编辑
            return formIdAndEditEnale;
        }
        for (PaasProcessTemplateEntityExt entityExt : templateList) {
            if (Objects.equals(entityExt.getAllowEditAfterFinished(), 1)) {
                formIdAndEditEnale.put(entityExt.getFormId(), true);
            } else {
                formIdAndEditEnale.put(entityExt.getFormId(), false);
            }
        }
        return formIdAndEditEnale;
    }

    @Override
    public boolean isApprovedEdit(Long appId, Long menuId, Long formId, UserVO loginUser, PaasFormDataEntityExt formData){
        boolean editAfterFinished = getEditAfterFinished(appId,menuId,formId,loginUser);
        if (editAfterFinished) {
            // 允许编辑
            return true;
        }
        // 单据审批通过的不允许编辑
        return !FlowStatusEnum.PASS.getType().equals(formData.getFlowStatus());
    }

    @Override
    public boolean isApprovedEdit(Long appId, Long menuId, Long formId, UserVO loginUser, Integer flowStatus) {
        boolean editAfterFinished = getEditAfterFinished(appId,menuId,formId,loginUser);
        if (editAfterFinished) {
            // 允许编辑
            return true;
        }
        // 单据审批通过的不允许编辑
        return !FlowStatusEnum.PASS.getType().equals(flowStatus);
    }

    @Override
    public boolean isApprovedEdit(boolean editAfterFinished, PaasFormDataEntityExt formData) {
        if (editAfterFinished) {
            // 允许编辑
            return true;
        }
        // 单据审批通过的不允许编辑
        return !FlowStatusEnum.PASS.getType().equals(formData.getFlowStatus());
    }

    /**
     * 检查审批通过后是否能编辑
     * @param editAfterFinished 审批后是否能编辑
     * @param list 数据列表
     * @throws XbbException xbb异常（不允许会抛异常）
     */
    @Override
    public void checkEditAfterFinished(boolean editAfterFinished, List<PaasFormDataEntityExt> list) throws XbbException {
        if (editAfterFinished) {
            // 允许编辑，返回
            return;
        }
        // 当list的长度为1时即为快速编辑
        if(list.size() == 1){
            PaasFormDataEntityExt paasFormDataEntityExt = list.get(0);
            boolean isEdit = isApprovedEdit(false,paasFormDataEntityExt);
            if(!isEdit){
                throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200017);
            }
        } else {
            // 记录编辑错误的条数
            int editErrorCount = 0;
            // 当不允许审批后可编辑时，审批后的不可进入编辑
            for (PaasFormDataEntityExt formDataEntityExt : list) {
                if(!isApprovedEdit(false,formDataEntityExt)){
                    editErrorCount ++;
                }
            }
            if(editErrorCount > 0){
                throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200017, MessageConstant.EDIT_DATA_ERROR, editErrorCount);
            }
        }
    }

    @Override
    public void checkEditAfterFinished(Map<Long, Boolean> editAfterFinishedMap, List<PaasFormDataEntityExt> list) throws XbbException {
        if(list.size() == 1){
            PaasFormDataEntityExt paasFormDataEntityExt = list.get(0);
            Boolean editable = editAfterFinishedMap.get(paasFormDataEntityExt.getFormId()) == null ? true : editAfterFinishedMap.get(paasFormDataEntityExt.getFormId());
            boolean isEdit = isApprovedEdit(editable,paasFormDataEntityExt);
            if(!isEdit){
                throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200017);
            }
        } else {
            // 记录编辑错误的条数
            int editErrorCount = 0;
            // 当不允许审批后可编辑时，审批后的不可进入编辑
            for (PaasFormDataEntityExt formDataEntityExt : list) {
                Boolean editable = editAfterFinishedMap.get(formDataEntityExt.getFormId()) == null ? true : editAfterFinishedMap.get(formDataEntityExt.getFormId());
                if(!isApprovedEdit(editable,formDataEntityExt)){
                    editErrorCount ++;
                }
            }
            if(editErrorCount > 0){
                throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200017, MessageConstant.EDIT_DATA_ERROR, editErrorCount);
            }
        }
    }

    @Override
    public Integer deleteByFormId(Long formId, String corpid) {
        return processTemplateDao.deleteByFormId(formId, corpid);
    }

    @Override
    public Integer enable(List<Long> enableList, String corpid, int enable) {
        if (CollectionsUtil.isEmpty(enableList)) {
            return 0;
        }
        return processTemplateDao.enable(enableList, corpid, enable);
    }
}
